#include "websocketServer.h"
#include <QWebSocket>

#include "base.qpb.h"
#include "gateway.qpb.h"
#include "user.qpb.h"
#include "notify.qpb.h"
#include "speech.qpb.h"
#include "message.qpb.h"
#include "friend.qpb.h"
#include "file.qpb.h"
#include "transmite.qpb.h"
#include "httpServer.h"


WebsocketServer* WebsocketServer::instance = nullptr;

WebsocketServer *WebsocketServer::getInstance()
{
    static WebsocketServer instance;
    return &instance;
}

bool WebsocketServer::init()
{
    // 连接信号槽
    // newConnection是要客户端连接到服务端后，才会触发的
    connect(&websocketServer, &QWebSocketServer::newConnection, this, [=]() {
        // 连接成功之后
        LOG() << "[websocket] 连接建立成功!";

        // 获取到用来通信的 socket 对象. nextPendingConnection 类似于 原生 socket 中的 accept

        QWebSocket* socket = websocketServer.nextPendingConnection();

        connect(socket, &QWebSocket::disconnected, this, [=]() {
            qDebug() << "[websocket] 连接断开!";
            disconnect(this, &WebsocketServer::sendTextResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendFriendRemove, this, nullptr);
            disconnect(this, &WebsocketServer::sendAddFriendApply, this, nullptr);
            disconnect(this, &WebsocketServer::sendAddFriendProcess, this, nullptr);
            disconnect(this, &WebsocketServer::sendCreateChatSession, this, nullptr);
            disconnect(this, &WebsocketServer::sendImageResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendFileResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendSpeechResp, this, nullptr);
        });

        connect(socket, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error) {
            LOG() << "[websocket] 连接出错! " << error;
        });

        connect(socket, &QWebSocket::textMessageReceived, this, [=](const QString& message) {
            LOG() << "[websocket] 收到文本消息!" << message;
        });

        connect(socket, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray) {
            LOG() << "[websocket] 收到二进制数据! " << byteArray.length();
        });

        connect(this, &WebsocketServer::sendTextResp, this, [=]() {
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyNewMessage notifyNewMessage;
            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::MessageInfo messageInfo = createTextMessageInfo(this->messageIndex++,"2000",avatar);
            notifyNewMessage.setMessageInfo(messageInfo);

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNewMessageInfo(notifyNewMessage);
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::CHAT_MESSAGE_NOTIFY);

            QByteArray body = notifyMessage.serialize(&serializer);

            socket->sendBinaryMessage(body);
            LOG() << "发送文本消息响应: " << messageInfo.message().stringMessage().content();
        });

        connect(this, &WebsocketServer::sendImageResp, this, [=]() {
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyNewMessage notifyNewMessage;
            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::MessageInfo messageInfo = createImageMessageInfo(this->messageIndex++,"2000",avatar);
            notifyNewMessage.setMessageInfo(messageInfo);

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNewMessageInfo(notifyNewMessage);
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::CHAT_MESSAGE_NOTIFY);

            QByteArray body = notifyMessage.serialize(&serializer);

            socket->sendBinaryMessage(body);
            LOG() << "发送图片消息";
        });

        connect(this, &WebsocketServer::sendFileResp, this, [=]() {
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyNewMessage notifyNewMessage;
            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::MessageInfo messageInfo = createFileMessageInfo(this->messageIndex++,"2000",avatar);
            notifyNewMessage.setMessageInfo(messageInfo);

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNewMessageInfo(notifyNewMessage);
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::CHAT_MESSAGE_NOTIFY);

            QByteArray body = notifyMessage.serialize(&serializer);

            socket->sendBinaryMessage(body);
            LOG() << "发送文件消息";
        });

        connect(this,&WebsocketServer::sendFriendRemove,this,[=](){
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::FRIEND_REMOVE_NOTIFY);

            lch_im::NotifyFriendRemove notifyFriendRemove;
            notifyFriendRemove.setUserId("1000");
            notifyMessage.setFriendRemove(notifyFriendRemove);

            QByteArray body = notifyMessage.serialize(&serializer);

            socket->sendBinaryMessage(body);
            LOG() << "通知对方好友被删除 userId=1000";
        });

        connect(this,&WebsocketServer::sendAddFriendApply,this,[=](){
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::FRIEND_ADD_APPLY_NOTIFY);

            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::UserInfo userInfo = createUserInfo(100,avatar);

            lch_im::NotifyFriendAddApply friendAddApply;
            friendAddApply.setUserInfo(userInfo);
            notifyMessage.setFriendAddApply(friendAddApply);

            QByteArray body = notifyMessage.serialize(&serializer);

            socket->sendBinaryMessage(body);
            LOG() << "通知对方好友申请数据";
        });

        connect(this,&WebsocketServer::sendAddFriendProcess,this,[=](bool agree){
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY);

            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::UserInfo userInfo = createUserInfo(100, avatar);

            lch_im::NotifyFriendAddProcess friendAddProcess;
            friendAddProcess.setUserInfo(userInfo);
            friendAddProcess.setAgree(agree);

            notifyMessage.setFriendProcessResult(friendAddProcess);

            QByteArray body = notifyMessage.serialize(&serializer);
            socket->sendBinaryMessage(body);
            LOG() << "通知好友申请的处理结果 userId=" << userInfo.userId() << ", agree=" << agree;
        });

        connect(this,&WebsocketServer::sendCreateChatSession,this,[=](){
            if(socket == nullptr) {
                LOG() << "socket 对象无效!";
                return;
            }

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY);

            QByteArray avatar = loadFileToQByteArray(":/resource/image/avatarDefault.png");
            lch_im::MessageInfo messageInfo = createTextMessageInfo(0, "2100", avatar);

            lch_im::ChatSessionInfo chatSessionInfo;
            chatSessionInfo.setChatSessionId("2100");
            chatSessionInfo.setSingleChatFriendId("");
            chatSessionInfo.setChatSessionName("新的群聊");
            chatSessionInfo.setPrevMessage(messageInfo);
            chatSessionInfo.setAvatar(avatar);

            lch_im::NotifyNewChatSession newChatSession;
            newChatSession.setChatSessionInfo(chatSessionInfo);

            notifyMessage.setNewChatSessionInfo(newChatSession);

            QByteArray body = notifyMessage.serialize(&serializer);
            socket->sendBinaryMessage(body);
            LOG() << "通知创建会话!";
        });

        connect(this, &WebsocketServer::sendSpeechResp, this, [=]() {
            // 此处就可以捕获到 socket 对象, 从而可以通过 socket 对象给客户端返回数据.
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }
            // 构造响应数据
            QByteArray avatar = loadFileToQByteArray(":/resource/image/defaultAvatar.png");
            lch_im::MessageInfo messageInfo = createSpeechMessageInfo(this->messageIndex++, "2000", avatar);

            lch_im::NotifyNewMessage notifyNewMessage;
            notifyNewMessage.setMessageInfo(messageInfo);

            lch_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(lch_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(notifyNewMessage);

            // 序列化
            QByteArray body = notifyMessage.serialize(&this->serializer);

            // 发送消息给客户端
            socket->sendBinaryMessage(body);

            LOG() << "发送语音消息响应";
        });

    });


    // 绑定端口，启动服务
    bool ok = websocketServer.listen(QHostAddress::Any,8001);
    return ok;
}
